import "./index.less";
import React, {useCallback, useEffect, useRef, useState} from 'react';
import Panel from "../../components/Panel";
import {Button, Input, Modal, message, notification, Select, Checkbox} from "antd";
import {Controlled as CodeMirror} from "react-codemirror2";
import 'codemirror/lib/codemirror.css';
import 'codemirror/mode/javascript/javascript';
import 'codemirror/lib/codemirror.js';
import 'codemirror/addon/display/fullscreen.js';
import 'codemirror/addon/hint/show-hint.css';
import 'codemirror/addon/fold/foldgutter.css';
import 'codemirror/addon/fold/foldcode.js';
import 'codemirror/addon/fold/foldgutter.js';
import 'codemirror/addon/fold/brace-fold.js';
import 'codemirror/addon/fold/comment-fold.js';
import 'codemirror/addon/edit/matchbrackets';
import "codemirror/addon/edit/closebrackets";
// import 'codemirror/addon/hint/show-hint';
import '../../utils/show-hint';
// import 'codemirror/addon/hint/javascript-hint';
import '../../utils/js-hint';
import {toSearchParams} from "../../utils";
import {HttpGet, HttpPost, Get} from "../../utils/httpUtil";
import {SuperSelect} from "../../components/SuperSelect";
import {useStoreState, useStoreActions} from 'easy-peasy'
import {isEmpty} from "codemirror/src/util/misc";
import {
    ApiOutlined
} from '@ant-design/icons';
import SimpleSelect from "./SimpleSelect";
import PageEditModal from "./PageEditModal";

function RuleEdit(props) {
    let actionStore = useStoreActions(actions => {
        return actions
    });
    let ruleS = useStoreState(state => state.RuleData.RuleData)
    const {location} = props;

    const editorRef = useRef();
    const sdEditorRef = useRef();
    const dEditorRef = useRef();
    const sEditorRef = useRef();
    const fEditorRef = useRef();
    const chapterEditorRef = useRef();
    const [rule, setRule] = useState({
        title: "",
        author: "",
        version: 0,
        group: "",
        icon: "",
        url: "",
        col_type: "",
        class_name: "",
        class_url: "",
        area_name: "",
        area_url: "",
        year_name: "",
        year_url: "",
        sort_name: "",
        sort_url: "",
        find_rule: "",
        search_url: "",
        searchFind: "",
        detail_col_type: "",
        detail_find_rule: "",
        sdetail_col_type: "",
        sdetail_find_rule: "",
        ua: "",
        preRule: "",
        last_chapter_rule: "",
        pages: "",
    });
    const [ruleImportModalVisible, setRuleImportModalVisible] = useState(false);
    const [ruleImport, setRuleImport] = useState("");
    const [ruleShareModalVisible, setRuleShareModalVisible] = useState(false);
    const [ruleShare, setRuleShare] = useState("");
    const [autoComplete, setAutoComplete] = useState(false);
    const [selectRule, setSelectRule] = useState();
    const [allRules, setAllRules] = useState([]);
    const [colTypes, setColTypes] = useState([]);
    const autoCompleteRef = useRef(false);
    const [pageParam, setPageParam] = useState({
        visible: false,
        rule: null
    })

    function onChange(key, value) {
        const ruleNew = {...rule};
        ruleNew[key] = value;
        setRule(ruleNew);
        actionStore.RuleData.addTodo(ruleNew)
    }

    useEffect(() => {
        setRule(ruleS)
    }, [location]);

    // 将表单转化为对象
    function rule2json() {
        const ruleJSON = JSON.parse(JSON.stringify(rule));
        ruleJSON['version'] = parseInt(rule['version']);
        return ruleJSON;
    }

    function clear() {
        setRule({
            title: "",
            author: "",
            version: 0,
            group: "",
            icon: "",
            url: "",
            col_type: "",
            class_name: "",
            class_url: "",
            area_name: "",
            area_url: "",
            year_name: "",
            year_url: "",
            sort_name: "",
            sort_url: "",
            find_rule: "",
            search_url: "",
            searchFind: "",
            detail_col_type: "",
            detail_find_rule: "",
            sdetail_col_type: "",
            sdetail_find_rule: "",
            ua: "",
            preRule: "",
            last_chapter_rule: "",
            pages: "",
        });
        actionStore.RuleData.addTodo(rule)
    }

    function importRule() {
        const rus = ruleImport.split("￥");
        if (rus.length < 3) {
            message.error("口令有误");
            return;
        }
        if (rus[1] !== "home_rule_v2" && rus[1] !== "home_rule") {
            message.error("口令有误，只能是首页规则口令");
            return;
        }
        rus[0] = "";
        rus[1] = "";
        const j = rus.join("￥").substring(2);
        const edit = JSON.parse(j);
        setRule(edit);
        setRuleImport("");
        setRuleImportModalVisible(false);
    }

    function shareRule() {
        const r = "海阔视界规则分享，当前分享的是：首页频道￥home_rule_v2￥" + JSON.stringify(rule);
        setRuleShare(r);
        setRuleShareModalVisible(true);
    }

    function saveRule() {
        (async () => {
            await HttpPost(`/saveRule`, rule2json()).then(json => {
                console.log('推送:', rule2json());
                if (json.isSuccess) {
                    notification.success({message: "保存规则成功", description: "保存规则成功"});
                } else {
                    notification.error({message: "保存规则失败", description: `保存规则失败!\nErrorMsg: ${json.errorMsg}`});
                }
            }).catch(err => {
                notification.error({message: "保存规则失败", description: `保存规则失败,无法连接到「APP」!\n${err}`});
            });
        })();
    }

    const refresh = useCallback(() => {
        if (editorRef.current != null) {
            editorRef.current.refresh();
        }
        if (sdEditorRef.current != null) {
            sdEditorRef.current.refresh();
        }
        if (dEditorRef.current != null) {
            dEditorRef.current.refresh();
        }
        if (sEditorRef.current != null) {
            sEditorRef.current.refresh();
        }
        if (fEditorRef.current != null) {
            fEditorRef.current.refresh();
        }
        if (chapterEditorRef.current != null) {
            chapterEditorRef.current.refresh();
        }
    }, []);

    function onCursorActivity(editor) {
        if (autoCompleteRef.current) {
            editor.showHint();
        }
    }

    function fetchAndBindRule(ruleTitle) {
        (async () => {
            await Get(`/getRuleContent?title=${ruleTitle}`).then(json => {
                if (json != null && json.length > 0) {
                    const edit = JSON.parse(json);
                    setRule(edit);
                } else {
                    notification.error({message: "获取规则失败", description: `获取规则失败,内容为空`});
                }
            }).catch(err => {
                notification.error({message: "获取规则失败", description: `获取规则失败,无法连接到「APP」!\n${err}`});
            });
        })();
    }

    useEffect(() => {
        autoCompleteRef.current = autoComplete;
    }, [autoComplete]);

    useEffect(() => {
        refresh();
    }, [rule]);

    useEffect(() => {
        const auto = localStorage.getItem("autoComplete");
        if (auto != null && auto === "true") {
            setAutoComplete(true);
        }
    }, []);

    useEffect(() => {
        if (ruleImportModalVisible) {
            setRuleImport("");
        }
    }, [ruleImportModalVisible]);

    useEffect(() => {
        if (selectRule != null && selectRule.length > 0) {
            fetchAndBindRule(selectRule);
        }
    }, [selectRule]);

    useEffect(() => {
        (async () => {
            await HttpGet(`/getAllRuleTitles`).then(json => {
                if (json != null && json.length > 0) {
                    setAllRules(json);
                }
            }).catch(err => {
                notification.error({message: "获取规则失败", description: `获取规则失败,无法连接到「APP」!\n${err}`});
            });
        })();
        (async () => {
            await HttpGet(`/getColTypes`).then(json => {
                if (json != null && json.length > 0) {
                    setColTypes(json);
                }
            }).catch(err => {
                notification.error({message: "获样式失败", description: `获取样式失败,无法连接到「APP」!\n${err}`});
            });
        })();
    }, []);

    useEffect(() => {
        const params = toSearchParams(location);
        try {
            const ruleTitle = params.get("rule");
            if (ruleTitle != null && ruleTitle.length > 0) {
                setSelectRule(ruleTitle);
                fetchAndBindRule(ruleTitle);
            }
        } catch (e) {
        }
    }, [location]);

    const codeMirrorOpt = {
        lineNumbers: true,
        lineWrapping: true,
        smartIndent: true,
        mode: {name: "javascript"},
        matchBrackets: true,
        autoCloseBrackets: true,
        showHint: true,
        indentWithTabs: true,
        extraKeys: {Tab: 'autocomplete'},
        hintOptions: {
            completeSingle: false,
        },
    };

    function renderTextArea(title, placeholder, key, maxRows = 3) {
        return (
            <div className={"mail-edit-head-bg"}>
                <h3 className={"head-title"}>{title}：</h3>
                <Input.TextArea
                    className={"mail-input"}
                    autoSize={{minRows: 1, maxRows}}
                    placeholder={placeholder}
                    value={rule[key]}
                    onChange={(e) => onChange(key, e.target.value)}/>
            </div>
        )
    }

    function renderSimpleSelect(title, key, placeholder, types) {
        return (
            <div className={"mail-edit-head-bg"}>
                <h3 className={"head-title"}>{title}：</h3>
                <SimpleSelect
                    placeholder={placeholder}
                    types={types || colTypes}
                    value={rule[key]}
                    onSelect={v => onChange(key, v)}
                />
            </div>
        )
    }

    function renderRuleEditor(title, span, key, editorRef) {
        return (
            <div className={"mail-edit-head-bg"}>
                <h3 className={"head-title"}>{title}：</h3><span>{span}</span>
                <div className={"code-mirror-bg"}>
                    <CodeMirror
                        onCursorActivity={onCursorActivity}
                        className={"code-mirror"}
                        value={rule[key]}
                        options={codeMirrorOpt}
                        onBeforeChange={(editor, data, value) => onChange(key, value)}
                        editorDidMount={editor => {
                            editorRef.current = editor;
                        }}
                    />
                </div>
            </div>
        )
    }

    function updatePages(page) {
        const pages = isEmpty(rule.pages) ? [] : JSON.parse(rule.pages);
        let isUpdate = false;
        for (let p of pages) {
            if (p.name === page.name) {
                isUpdate = true
                for (const key of Object.keys(page)) {
                    p[key] = page[key]
                }
                break
            }
        }
        if (!isUpdate) {
            pages.push(page);
        }
        onChange("pages", JSON.stringify(pages));
        setPageParam({...pageParam, visible: false});
    }

    const pages = isEmpty(rule.pages) ? [] : JSON.parse(rule.pages);

    return (
        <div className={"rule-edit"}>
            <div style={{
                width: 120,
                overflow: 'auto',
                height: '100vh',
                position: 'fixed',
                right: 0,
                marginRight: 20
            }}>
                <div style={{marginBottom: 10}}><Button type={"primary"} onClick={saveRule}>保存规则</Button></div>
                <div style={{marginBottom: 10}}><Button onClick={shareRule}>生成口令</Button></div>
                <div style={{marginBottom: 10}}><Button onClick={() => setRuleImportModalVisible(true)}>口令导入</Button>
                </div>
                <div style={{marginBottom: 10}}><Button onClick={clear}>清空表单</Button></div>
            </div>
            <div style={{marginRight: 120}}>

                <div className={"mail-edit-head-bg"}>
                    <h3 className={"head-title"}>选择规则：</h3>
                    <SuperSelect
                        optionFilterProp="children"
                        showSearch={true}
                        dropdownMatchSelectWidth={false}
                        className={"super-select"}
                        value={selectRule}
                        onSelect={setSelectRule}>
                        {allRules.map(rule => <Select.Option value={rule}>{rule}</Select.Option>)}
                    </SuperSelect>
                </div>

                <Panel title='基础信息' titleIcon={<ApiOutlined className={'title-icon'}/>}>
                    <div style={{padding: 15}}>
                        {renderTextArea("规则名称", "规则名称", "title", 1)}
                        {renderTextArea("规则作者", "规则作者（author）", "author", 1)}
                        {renderTextArea("规则版本", "规则版本（version）", "version", 1)}
                        {renderTextArea("频道分组", "频道分组（名称前加①、②等序号可排序）", "group", 1)}
                        {renderTextArea("图标地址", "规则图标地址（支持色值）", "icon", 1)}
                    </div>
                </Panel>

                <Panel title='基础规则' titleIcon={<ApiOutlined className={'title-icon'}/>}>
                    <div style={{padding: 15}}>
                        {renderTextArea("频道链接", "频道链接（可不填，可只填搜索相关内容）", "url")}
                        {renderSimpleSelect("显示样式", "col_type")}
                        {renderTextArea("分类名称", "分类名称（class_name）", "class_name", 5)}
                        {renderTextArea("分类替换", "分类替换词（class_url）", "class_url", 5)}
                        {renderTextArea("地区名称", "地区名称（area_name）", "area_name", 5)}
                        {renderTextArea("地区替换", "地区替换词（area_url）", "area_url", 5)}
                        {renderTextArea("年代名称", "年代名称（year_name）", "year_name", 5)}
                        {renderTextArea("年代替换", "年代替换词（year_url）", "year_url", 5)}
                        {renderTextArea("排序名称", "排序名称（sort_name）", "sort_name", 5)}
                        {renderTextArea("排序替换", "排序替换（sort_url）", "sort_url", 5)}

                        {renderTextArea("搜索链接", "搜索链接（search_url，用**作为关键词占位符）", "search_url", 5)}
                        {renderSimpleSelect("二级样式", "detail_col_type")}
                        {renderSimpleSelect("搜二样式", "sdetail_col_type")}
                        {renderSimpleSelect("全局UA", "ua", "规则全局UA（以url里面的ua优先，为空默认mobile，可选auto/mobile/pc）",
                            ["auto", "mobile", "pc"])}
                    </div>
                </Panel>

                <Panel title='解析规则' titleIcon={<ApiOutlined className={'title-icon'}/>} subTitle={<span>Tips：按Tab键可以自动补全代码
                    <Checkbox checked={autoComplete} onChange={e => {
                        localStorage.setItem("autoComplete", e.target.checked + "");
                        setAutoComplete(e.target.checked);
                    }}
                              style={{marginLeft: 10}}>动态补全</Checkbox></span>}>
                    <div style={{padding: 15}}>
                        {renderRuleEditor("解析规则", "（列表;标题;图片;描述;链接）", "find_rule", fEditorRef)}
                        {renderRuleEditor("搜索解析", "（列表;标题;链接;描述;详情;图片）", "searchFind", sEditorRef)}
                        {renderRuleEditor("二级解析", "（列表;标题;图片;描述;链接）", "detail_find_rule", dEditorRef)}
                        {renderRuleEditor("搜二解析", "（列表;标题;图片;描述;链接）", "sdetail_find_rule", sdEditorRef)}
                        {renderRuleEditor("最新章节", "", "last_chapter_rule", chapterEditorRef)}
                        {renderRuleEditor("JS预处理", "（解析规则和搜索解析规则前执行）", "preRule", editorRef)}
                    </div>
                </Panel>

                <Panel title='子页面' titleIcon={<ApiOutlined className={'title-icon'}/>}>
                    <div style={{padding: 15}}>
                        {pages.map(page => {
                            return <Button className={"pages-btn"}
                                           key={page.name}
                                           onClick={() => setPageParam({
                                               visible: true,
                                               rule: page
                                           })}>{page.name}</Button>
                        })}
                        <Button type={"primary"} className={"pages-btn"}
                                onClick={() => setPageParam({visible: true, rule: {}})}>新增页面</Button>
                    </div>
                </Panel>
            </div>
            <Modal
                okText={"导入"}
                cancelText={"取消"}
                title={"口令导入"}
                visible={ruleImportModalVisible}
                onCancel={() => setRuleImportModalVisible(false)}
                onOk={importRule}
            >
                <Input.TextArea
                    rows={20}
                    placeholder={"请输入口令，只能海阔视界开头"}
                    value={ruleImport}
                    onChange={(e) => setRuleImport(e.target.value)}/>
            </Modal>
            <Modal
                okText={"确定"}
                cancelText={"取消"}
                title={"请自行复制下面的口令"}
                visible={ruleShareModalVisible}
                onCancel={() => setRuleShareModalVisible(false)}
                onOk={() => setRuleShareModalVisible(false)}
            >
                <Input.TextArea
                    rows={20}
                    value={ruleShare}
                    onChange={(e) => setRuleShare(e.target.value)}/>
            </Modal>
            <PageEditModal
                colTypes={colTypes}
                visible={pageParam.visible}
                rule={pageParam.rule}
                dismiss={() => setPageParam({...pageParam, visible: false})}
                save={updatePages}
            />
        </div>
    );
}

export default RuleEdit;
